package com.ehotting.mqbd.loader.task;

import com.ehotting.eaf.core.DateHelper;
import com.ehotting.eaf.core.snow.SnowflakeUtil;
import com.ehotting.eaf.redis.service.RedisService;
import com.ehotting.edsta.mqbd.api.enums.SysModuleEnum;
import com.ehotting.mqbd.api.MQDBConstants;
import com.ehotting.mqbd.api.bean.ConsumerNodeBean;
import com.ehotting.mqbd.api.bean.solver.SolverCountBean;
import com.ehotting.mqbd.api.bean.solver.SolverStateBean;
import com.ehotting.mqbd.api.bean.solver.ModuleInfoBean;
import com.ehotting.mqbd.api.enums.SolveStepEnum;
import com.ehotting.mqbd.api.bean.MqApplicationContext;
import com.ehotting.mqbd.core.logger.LOGGER_KEY;
import com.ehotting.mqbd.core.manager.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.scheduling.annotation.Scheduled;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;


public class SolverCountLoader {

    private static final Logger logger = LoggerFactory.getLogger(SolverCountLoader.class);

    private SolverCountManager solverCountManager;
    private SolverStateManager solverStateManager;
    private RedisService redisService;
    private MqQueueManager mqQueueManager;
    private ConsumerNodeManager consumerNodeManager;
    private ModuleManager moduleManager;
    private SolverInfoManager solverInfoManager;

    public SolverCountLoader(SolverCountManager solverCountManager,
                             SolverStateManager solverStateManager,
                             MqQueueManager mqQueueManager,
                             RedisService redisService,
                             ConsumerNodeManager consumerNodeManager,
                             ModuleManager moduleManager,
                             SolverInfoManager solverInfoManager) {
        this.solverCountManager = solverCountManager;
        this.solverStateManager = solverStateManager;
        this.mqQueueManager = mqQueueManager;
        this.redisService = redisService;
        this.consumerNodeManager = consumerNodeManager;
        this.moduleManager = moduleManager;
        this.solverInfoManager = solverInfoManager;
    }

    @Scheduled(initialDelay=20000, fixedRate=10000)
    public void invoke(){
        MDC.put(LOGGER_KEY.TRACE_ID, SnowflakeUtil.nextId64());
        String time = DateHelper.toString(new Date(),DateHelper.STD_FORMAT);
        boolean lock = redisService.checkLock(MQDBConstants.REDIS_LOCK_KEY_COUNT,time,1000L*30);
        if(lock == false){
            logger.info("ServerCount is locked,return.");
            return;
        }
        logger.info("Start count action:{}",time);
        action();
    }


    public void action(){
        List<SolverCountBean> serverCountList =  solverCountManager.countByState();
        serverCountList.stream().forEach(serverCount->{
            logger.info("Start count modules[{}].",serverCount.getModule());

            if(serverCount.getModule().equals(SysModuleEnum.PBC_DESIGN.getCode())
                    || serverCount.getModule().equals(SysModuleEnum.TESTABILITY.getCode()) || serverCount.getModule().equals(SysModuleEnum.TESTABILITY.getCode())){
                logger.info("Module[{}] not count,return.",serverCount.getModule());
                return;
            }

            ModuleInfoBean moduleInfo  = moduleManager.getByModule(serverCount.getModule());
            if(moduleInfo==null){
                logger.info("moduleInfo[{}] is null,return.",serverCount.getModule());
                return;
            }

            if(moduleInfo.getSolveStep() == SolveStepEnum.ONE){
                long count = mqQueueManager.getQueueSize(createMqApplicationContext(serverCount.getModule()));
                serverCount.setQueueCount(count);
            }else{
                List<MqApplicationContext> applicationContextList = createMqApplicationContextList(serverCount.getModule());
                List<SolverStateBean> serverStateList = solverInfoManager.getByModule(serverCount.getModule());
                for(SolverStateBean serverState : serverStateList){
                    long count = mqQueueManager.getQueueSize(applicationContextList, serverState);
                    serverState.setQueueSize(count);
                    serverCount.setQueueCount(serverCount.getQueueCount()+count);
                    solverStateManager.saveStatue(serverState);
                }
                serverCount.getServerList().clear();
                serverCount.getServerList().addAll(serverStateList);
            }

        });
        solverCountManager.saveCount(serverCountList);
    }

    private List<MqApplicationContext> createMqApplicationContextList(String module){
        List<ConsumerNodeBean> consumerNodeList = consumerNodeManager.getLiveList();
        List<MqApplicationContext> applicationContextList = new ArrayList<MqApplicationContext>();
        for(ConsumerNodeBean c : consumerNodeList){
            MqApplicationContext mqApplicationContext = new MqApplicationContext();
            mqApplicationContext.setConsumerHost(c.getIp());
            mqApplicationContext.setModule(module);
            applicationContextList.add(mqApplicationContext);
        }
        return applicationContextList;
    }

    private MqApplicationContext createMqApplicationContext(String module){
        MqApplicationContext mqApplicationContext = new MqApplicationContext();
        mqApplicationContext.setConsumerHost(MQDBConstants.DISPATCHER_HOST);
        mqApplicationContext.setModule(module);
        return mqApplicationContext;
    }

}